package com.fante.dubbo.manage.config;

import com.fante.dubbo.manage.shiro.MyShiroRealm;
import com.fante.dubbo.manage.shiro.cache.ShiroRedisCacheManager;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.data.redis.core.RedisTemplate;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

/**
 * Shiro的配置
 * @Author liubao
 * @Date 2020/6/6
 */
@Configuration
public class MyShiroConfig {

    private static final transient Logger log = LoggerFactory.getLogger(MyShiroConfig.class);

    @Resource(name = "shiroRedisTemplate")
    private RedisTemplate redisTemplate;

    //TODO:全局缓存时间，单位为秒
    @Value("${hdw.jwt.expiration}")
    private int cacheLive;

    //TODO:全局缓存名称前缀，默认为应用名
    @Value("${spring.application.name}")
    private String cacheKeyPrefix;

    /**
     * 配置身份验证成功，跳转路径
     * @param securityManager
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        Map<String, String> filterChainDefinitionMap = new HashMap<String, String>();
        filterChainDefinitionMap.put("/static/**", "anon");    // 静态资源匿名访问
        filterChainDefinitionMap.put("/kaptcha/**", "anon");    // 静态资源匿名访问
        filterChainDefinitionMap.put("/employees/login", "anon");// 登录匿名访问
        filterChainDefinitionMap.put("/logout", "logout");    // 用户退出，只需配置logout即可实现该功能
        filterChainDefinitionMap.put("/**", "authc");        // 其他路径均需要身份认证，一般位于最下面，优先级最低
        shiroFilterFactoryBean.setLoginUrl("/login");        // 登录的路径
        shiroFilterFactoryBean.setSuccessUrl("/index");    // 登录成功后跳转的路径
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");    // 验证失败后跳转的路径
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

    /**
     * 配置Shiro生命周期处理器
     * @return
     */
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    /**
     * 安全管理器  Shiro的核心
     * @return
     */
    @Bean
    public DefaultWebSecurityManager defaultWebSecurityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myShiroRealm());
        return securityManager;
    }

    /**
     * 自己定义的Realm
     * @return
     */
    @Bean
    public MyShiroRealm myShiroRealm() {
        MyShiroRealm myShiroRealm = new MyShiroRealm();
        return myShiroRealm;
    }

    /**
     * 配置加密匹配, 使用MD5加密, 进行1024次加密
     * @return
     */
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("MD5");
        hashedCredentialsMatcher.setHashIterations(1024);
        return hashedCredentialsMatcher;
    }

    /**
     * 开启 Shiro注解
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        // 配置自己设置的安全管理器
        authorizationAttributeSourceAdvisor.setSecurityManager(defaultWebSecurityManager());
        return authorizationAttributeSourceAdvisor;
    }

    /**
     * 自动创建代理类，若不添加，Shiro的注解可能不会生效
     * @return
     */
    @Bean
    @DependsOn({"lifecycleBeanPostProcessor"})
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
        return defaultAdvisorAutoProxyCreator;
    }

    /**
     * 缓存管理器
     * @return
     */
    public CacheManager shiroRedisCacheManager() {
        ShiroRedisCacheManager redisCacheManager=new ShiroRedisCacheManager(cacheLive*1000,cacheKeyPrefix+"-shiro-cache-",redisTemplate);
        return redisCacheManager;
    }
}
